package com.powergisol.gis.service.impl;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import	java.net.SocketAddress;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.powergisol.gis.dao.TabServiceMapper;
import com.powergisol.gis.dao.TabUserMapper;
import com.powergisol.gis.entity.TabService;
import com.powergisol.gis.entity.TabUser;
import com.powergisol.gis.service.TabDataService;
import com.powergisol.gis.util.PropertyUtil;
import com.powergisol.gis.util.Result;
import com.powergisol.gis.vo.TabServiceVo;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static java.lang.Integer.valueOf;

/**
 * Date: 2019/7/10  9:26
 * Description:
 */
@Service
public class TabDataServiceImpl implements TabDataService {
    private static Logger logger = LoggerFactory.getLogger(TabDataServiceImpl.class);
    @Value("${collectionName}")
    private String collectionName;
    @Autowired
    private TabServiceMapper tabServiceMapper;

    @Autowired
    private TabUserMapper tabUserMapper;

    @Autowired
    private GridFSBucket gridFSBucket;

    @Value("${3dmodel-url}")
    private String dmodelUrl;
    @Value("${wms-url}")
    private String wmsUrl;
//    @Value("${file-url}")
//    private String fileUrl;
//    @Value("${style-url}")
//    private String styleUrl;


    @Override
    public String selectLevelById(Integer type){
        return tabServiceMapper.selectLevelById(type);
    }

    @Override
    public List<TabServiceVo> tabServiceList(TabServiceVo vo) {
        return tabServiceMapper.tabServiceList(vo);
    }

    @Override
    public List<Map<String, Object>> getDataType(TabServiceVo vo) {
        //查询数据类型的层级编码
        String levelCode = tabServiceMapper.selectLevelById(vo.getType());
        vo.setLevelCode(levelCode);
        return tabServiceMapper.getDataType(vo);
    }
    @Override
    public Map<String, Object> getDataFile(Integer staticNum) {
        return tabServiceMapper.getDataFile(staticNum);
    }

    @Override
    public List<Map<String, Object>> getServiceType(Integer staticNum) {
        return tabServiceMapper.getServiceType(staticNum);
    }

    @Override
    public int upDataPath(String filePath, Integer staticNum) {
        return tabServiceMapper.upDataPath(filePath, staticNum);
    }

    @Override
    public Integer getServiceNameNum(String name){
        return tabServiceMapper.getServiceNameNum(name);
    }

    @Override
    public Result releaseTabService(TabServiceVo vo) {
        Result result = new Result();
        //服务名称不能重复
        List<TabServiceVo> tabServiceVo = tabServiceMapper.getTabServiceByCondition(vo);
        if(tabServiceVo.size()>0){
            return result.failure(-3,"服务名称不能重复");
        }
        //uuid不能重复
        TabService tabService = tabServiceMapper.getByUuid(vo.getUuid());
        if(null != tabService){
            return result.failure(-3,"服务信息重复，请关闭窗口再试");
        }
        //如果是高程缓存文件（*.tif）且转换为terrain格式则样式固定
        switch (vo.getServiceType()){
           case 1:
               vo.setStyleUrl("raster.sld");
               break;
           case 3:
               vo.setStyleUrl("dem.sld");
               break;
//            case 4:
//                if(null == vo.getStyleUrl()){
//                    vo.setStyleUrl(shpStyleUrl);
//                }
//               break;
        }
        if(null != vo.getFileUrl()){
            vo.setOriginUrl(vo.getFileUrl());
        }
        vo.setFileUrl(null);
        TabUser user = tabUserMapper.getByUserName(vo.getCurrentUserName());
        vo.setUserId(user.getId());
        vo.setCurrentUserId(user.getId());
        vo.setReleaseTime(new Date());
        tabServiceMapper.insertSelective(vo);
        tabServiceMapper.insertUserService(vo.getCurrentUserId(),vo.getId());
        return result.success("发布成功");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Result updateTabService(TabServiceVo vo) {
        Result result = new Result();
        logger.info("{}修改服务={}",vo.getUuid(),vo.getFileUrl());
        TabService tabService = tabServiceMapper.getTabServiceCondition(vo);
        if(null != tabService){
            tabService.setUploadTime(new Date());
            tabService.setFileUrl(vo.getFileUrl());
            tabService.setOriginUrl(vo.getOriginUrl());
            tabServiceMapper.updateByPrimaryKeySelective(tabService);
        }else{
            return result.failure(404,"服务不存在");
        }
        return result.success("修改成功");
    }
    @Override
    public Result updateTabService(TabService tabService) {
        Result result = new Result();
        TabService tabService1 = tabServiceMapper.getByUuid(tabService.getUuid());
        if(null != tabService1.getId()){
            tabService.setUploadTime(new Date());
            tabService1.setKeyword(tabService.getKeyword());
            tabService1.setDescription(tabService.getDescription());
            tabService1.setTitle(tabService.getTitle());
            tabServiceMapper.updateByPrimaryKeySelective(tabService1);
        }else{
            return result.failure(404,"服务不存在");
        }
        return result.success("修改成功");
    }

    @Override
    public Result getTabServiceById(Integer id) {
        Result result = new Result();
        TabServiceVo vo = new TabServiceVo();
        vo.setId(id);
        List<TabServiceVo> listVo = tabServiceMapper.getTabServiceByCondition(vo);
        TabServiceVo tabServiceVo = listVo.size()>0?listVo.get(0):null;
        result.setData(tabServiceVo);
        return result.success("获取成功");
    }

    @Override
    public Result upTabServiceState( TabService tabService,Integer state, String name, String serviceCoordinate,String encodingType) {
        Result result = new Result();
        if(null == tabService){
            return result.failure(404,"服务不存在");
        }
        if(3 == tabService.getState() && state == 1){
            return result.failure(403,"服务不可用");
        }
        if(null != serviceCoordinate){
            tabService.setServiceCoordinate(serviceCoordinate);
        }
        if(null != encodingType){
            tabService.setTitle(encodingType);
        }
        //设置服务url
        if(1 == state && (null ==tabService.getServiceUrl()||("").equals(tabService.getServiceUrl()))){
            Integer serviceType = tabService.getServiceType();
            switch (serviceType){
                case 1:
                case 4:
                    tabService.setServiceUrl(wmsUrl+tabService.getName());
                    break;
                case 3:
                    if("terrain".equals(tabService.getChangeType())){
                        tabService.setServiceUrl(dmodelUrl+tabService.getName());
                    }else{
                        tabService.setServiceUrl(wmsUrl+tabService.getName());
                    }
                    break;
                case 2:
                case 5:
                case 6:
                case 7:
                case 8:
                    tabService.setServiceUrl(dmodelUrl+tabService.getName());
                    break;

            }
        }
        String styleUrl = tabService.getStyleUrl();
        if(null != styleUrl && styleUrl.contains(File.separator)){
            tabService.setStyleUrl(styleUrl.substring(styleUrl.lastIndexOf(File.separator)+1,styleUrl.length()));
        }
        tabService.setState(state);
        tabServiceMapper.updateByPrimaryKeySelective(tabService);
        result.setData(tabService);
        return result.success("操作成功");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Result getTabServiceByName(String name) {
        Result result = new Result();
        TabServiceVo vo = new TabServiceVo();
        vo.setName(name);
        List<TabServiceVo> listVo = tabServiceMapper.getTabServiceByCondition(vo);
        TabServiceVo tabServiceVo = listVo.size()>0?listVo.get(0):null;
        if(null != tabServiceVo){
            TabService tabService = tabServiceMapper.getByName(name);
            String fileUrl = tabServiceVo.getFileUrl();
            if(StrUtil.isBlank(fileUrl)){
                tabServiceVo.setState(3);
                tabServiceMapper.updateState("3",tabService.getId());
            }else{
                File file = new File(fileUrl);
                if(!file.exists()){
                    tabServiceVo.setState(3);
                    tabServiceMapper.updateState("3",tabService.getId());
                }else{
                    if(tabService.getState()==3){
                        tabServiceVo.setState(0);
                        tabServiceMapper.updateState("0",tabService.getId());
                    }
                }
            }

        }
        result.setData(tabServiceVo);
        return result.success("获取成功");
    }

    @Override
    public TabServiceVo getVoByName(String name) {
        TabServiceVo vo = new TabServiceVo();
        vo.setName(name);
        List<TabServiceVo> listVo = tabServiceMapper.getTabServiceByCondition(vo);
        vo = listVo.size()>0?listVo.get(0):null;
        return vo;
    }


    @Override
    public Result getTabServiceByNameForRemote(String name) {
        Result result = new Result();
        TabServiceVo vo = new TabServiceVo();
        vo.setName(name);
        List<TabServiceVo> listVo = tabServiceMapper.getTabServiceByCondition(vo);
        TabServiceVo tabServiceVo = listVo.size()>0?listVo.get(0):null;
        if(null != tabServiceVo && null != tabServiceVo.getStyleUrl()){
            String userDir = System.getProperty("user.dir");
            userDir = userDir.substring(0,userDir.lastIndexOf(File.separator));
            tabServiceVo.setStyleUrl(userDir+File.separator+"serviceData"+File.separator+"style"+File.separator+tabServiceVo.getStyleUrl());
        }
        result.setData(tabServiceVo);
        return result.success("获取成功");
    }

    @Override
    public Result delTabServiceByUuid(String uuid) {
        TabServiceVo vo = new TabServiceVo();
        vo.setUuid(uuid);
        TabService tabService = tabServiceMapper.getTabServiceCondition(vo);
        if(tabService==null){
            return new Result().failure(-3,"服务不存在");
        }
        tabServiceMapper.deleteByPrimaryKey(tabService.getId());
        tabServiceMapper.deleteUserService(tabService.getId());
        return new Result().success("删除成功");
    }

    @Override
    public TabService getByName(String name) {
        return tabServiceMapper.getByName(name);
    }

    @Override
    public TabService getByUuid(String uuid) {
        return tabServiceMapper.getByUuid(uuid);
    }

    @Override
    public int upTabServiceStyleUrl(TabService tabService, String resultType) {
        JSONObject object = JSONObject.parseObject(resultType);
        String geometry = object.getString("geometry");
        if("MULTIPOLYGON".equalsIgnoreCase(geometry)){
            tabService.setStyleUrl("default_polygon.sld");
        }else if("MULTILINESTRING".equalsIgnoreCase(geometry)){
            tabService.setStyleUrl("default_line.sld");
        }else if("POINT".equalsIgnoreCase(geometry)){
            tabService.setStyleUrl("default_point.sld");
        }
        return tabServiceMapper.updateByPrimaryKey(tabService);
    }

    @Override
    @Async
    public void writeToDisk(String absolutePath, Long len, GridFSFile gridFSFile , int size){
        File file = new File(absolutePath);
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        try {
            if(!file.exists()){
                ObjectId objectId = gridFSFile.getObjectId();
                GridFSDownloadStream stream = gridFSBucket.openDownloadStream(objectId);
                FileOutputStream out = new FileOutputStream(file.getAbsoluteFile());
                /** loop time */
                BigDecimal num = new BigDecimal(len).divide(new BigDecimal(size),0,BigDecimal.ROUND_UP);
                Integer cnt = valueOf(num.toString());
                byte[] bts = new byte[size];
                while (cnt-- > 0){
                    int tmp = stream.read(bts);
                    out.write(bts,0,tmp);
                }
                out.close();
            }
        }catch (Exception e){
            logger.error("mongodb读出写入磁盘异常",e);
        }
    }

}
